package snd;

import javax.sound.sampled.*;

import java.io.*;
import java.util.ArrayList;
import java.util.Random;

public class SndPlayer {
		private static final int	EXTERNAL_BUFFER_SIZE = 128000;
		private byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];

		private static final float maxGain = 12;
		private static final float minGain = -12;
		private float vol = 0;
		private int nBytesRead = 0;
		private int nBytesWritten = 0;

		private static final String path = "./snd/";
		private static final String ext  = ".aiff";
		
		private SourceDataLine	line = null;
		private AudioInputStream  as = null;

		public SndPlayer() {
			super();
		}

		public static void main(String[] args)
		{
			SndPlayer player = new SndPlayer();
			
			ArrayList<Integer> l = new ArrayList<Integer>();
			
			l.add(3);
			l.add(5);
			l.add(8);
//			
			player.playRoute(l);
			
//			player.playLocate(l);
//			player.playNopathto(8);
//			player.playNopebble();
//			player.putLine(player.genFilename("1_"));
//			player.putLine(player.genFilename("_2"));
			
//			player.playArrived();
			player.playWait();
			player.playNopathto(3);
//			player.decreaseVol();
//			player.decreaseVol();
//			player.playGoal(5);
//
//			player.vol = -13;
//			for (int i=0; i<15; i++) {
//				player.increaseVol();
//			}
//			for (int i=0; i<15; i++) {
//				player.decreaseVol();
//			}

//			player.playGoal(6);
			System.exit(0);
		}
		
		public void increaseVol() {
			vol += 2;
			vol = Math.min(vol, maxGain);
			putLine(path + "pop.wav");
		}
		
		public void decreaseVol() {
			vol -= 2;
			vol = Math.max(vol, minGain);
			putLine(path + "pop.wav");
		}
				
		// New added, reverse order
		public void playRoute(ArrayList<Integer> l) {
			int id;
			switch (l.size()) {
			case 1:
				id = l.get(0);
				putLine(genFilename("route"));
				putLine(genFilename(String.valueOf(id)));
				break;
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
				int i;
				putLine(genFilename("route"));
				for (i=l.size()-1; i>0; i--) {
					id = l.get(i);
					putLine(genFilename(String.valueOf(id) + "_"));
				}
				id = l.get(0);
				putLine(genFilename("_" + String.valueOf(id)));
				break;
			default:
				break;
			}

		}
		
		// New added
		public void playLocate(ArrayList<Integer> l) {
			int id;
			switch (l.size()) {
			case 0:
				playNopebble();
				break;
			case 1:
				id = l.get(0);
				putLine(genFilename("locate"));
				putLine(genFilename(String.valueOf(id)));
				break;
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
				int i;
				putLine(genFilename("locate"));
				for (i=0; i<l.size()-1; i++) {
					id = l.get(i);
					putLine(genFilename(String.valueOf(id) + "_"));
				}
				id = l.get(i);
				putLine(genFilename("_" + String.valueOf(id)));
				break;
			default:
				break;
			}
		}
		
		// added on 9/29, for UIST demo
		public void play(String clipName) {
			putLine(genFilename(clipName));
		}

		// added on 4/29, reached a checkpoint
		public void playCheckpoint() {
			putLine(genFilename("checkpoint"));			
		}

		// added on 4/29, still moving
		public void playMoving() {
			Random randomGenerator = new Random();
			int r = randomGenerator.nextInt(2);
			if (r==0) {
				putLine(genFilename("moving"));	
			} else {
				putLine(genFilename("ontheway"));
			}
		}

		// added on 4/29, found the next checkpoint
		public void playFoundnext() {
			putLine(genFilename("foundnext"));			
		}

		// added on 4/29, when user pressed "0"
		public void playStop() {
			putLine(genFilename("stop"));			
		}

		// New added
		public void playNopebble() {
			putLine(genFilename("nopebble"));
		}
		
		// New added
		public void playNopathto(int id) {
			putLine(genFilename("nopathto"));
			putLine(genFilename(String.valueOf(id)));
		}
		
		// New added
		public void playNopath() {
			putLine(genFilename("nopath"));
		}
		
		public void playCantfind() {
			putLine(genFilename("cantfind"));
		}
		
		public void playLost() {
			putLine(genFilename("lost"));
		}
		
		public void playGoal(int id) {
			putLine(genFilename("goto" + String.valueOf(id)));
		}
		
		public void playArrived() {
			putLine(genFilename("arrived"));
		}
		
		public void playWait() {
			putLine(genFilename("wait"));
		}
		
		public String genFilename(String str) {
			return path + str + ext;
		}
		
		public int putLine(String strFilename) {
			File	soundFile = new File(strFilename);
			nBytesRead = 0;
			
			try
			{
				as = AudioSystem.getAudioInputStream(soundFile);
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return -1;
			}
			
			AudioFormat	audioFormat = as.getFormat();
			DataLine.Info	info = new DataLine.Info(SourceDataLine.class, audioFormat);
			try
			{
				line = (SourceDataLine) AudioSystem.getLine(info);
				line.open(audioFormat);
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return -1;
			}
			
	        if (line.isControlSupported(FloatControl.Type.MASTER_GAIN)) { 
	            FloatControl volume = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
	            volume.setValue(vol);
	        } 

			line.start();
			
			while (nBytesRead != -1)
			{
				try
				{
					nBytesRead = as.read(abData, 0, abData.length);
				}
				catch (IOException e)
				{
					e.printStackTrace();
					return -1;
				}
				if (nBytesRead >= 0)
				{
					nBytesWritten = line.write(abData, 0, nBytesRead);
				}
			}
			line.drain();
			line.close();
			return nBytesWritten;
		}


	}